package cn.itsource.basic.service.impl;

import cn.itsource.basic.constant.BaseConstants;
import cn.itsource.basic.dto.PhoneRegisterDto;
import cn.itsource.basic.exception.BusinessException;
import cn.itsource.basic.service.IVerifyCodeService;
import cn.itsource.basic.util.SmsUtil;
import cn.itsource.basic.util.StrUtils;
import cn.itsource.basic.util.VerifyCodeUtils;
import cn.itsource.user.domain.User;
import cn.itsource.user.mapper.UserMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.net.BindException;
import java.util.concurrent.TimeUnit;

@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private RedisTemplate redisTemplate;
    
    @Autowired
    private UserMapper userMapper;

    @Override
    public String image(String imageCodeKey) {
        /*
        * 1.产生4位随机验证码
        * 2.将验证码存入redis  key:imageCodeKey
        * 3.产生Base64字符串返回
        * */

//        1.产生4位随机验证码
        String imageCode = StrUtils.getComplexRandomString(4);
//        2.将验证码存入redis  key:imageCodeKey
        redisTemplate.opsForValue().set(imageCodeKey,imageCode,3, TimeUnit.MINUTES);
//        3.产生Base64字符串返回
        return VerifyCodeUtils.VerifyCode(100,40,imageCode);
    }

    /*1.参数非空校验
    2.验证图形验证码是否正确
    3.查询手机号是否被注册
    4.通过   业务键（register:）+手机号   获取是否存在短信验证码
    4.1.不存在（第一次发送或者过期）
    4.1.1.生成手机验证码
    4.1.2.以   业务键（register:）+手机号  为key,以  验证码+“：”+当前时间戳 为value,把验证码存入redis
    4.1.3.发送手机验证码给用户

    4.2.存在
    4.2.1.判断发送时间是否小于1分钟
    4.2.1.1.如果小于1分钟 使劲骂 滚！
    4.2.1.2.如果大于1分钟 取出验证码，为key,以  验证码+“：”+当前时间戳 为value,把验证码存入redis
    4.2.1.3.发送手机验证码给用户*/
    @Override
    public void sendSmsCode(PhoneRegisterDto phoneRegisterDto) {
        /*
        * 参数校验
        * */
        String phone = phoneRegisterDto.getPhone();
        String type = phoneRegisterDto.getType();
        if (StringUtils.isBlank(phone) || StringUtils.isBlank(type) ){
            throw new BusinessException("参数不能为空");
        }

        if (phoneRegisterDto.getType().equals("register")){
            sendRegisterCode(phoneRegisterDto);
        }else {
            sendBinderCode(phoneRegisterDto);
        }
    }

    /*
    发送微信绑定的验证码
    * */
    private void sendBinderCode(PhoneRegisterDto phoneRegisterDto) {

        String  prefixAndPhone = BaseConstants.VerifyCodeConstants.USER_PHONE_BINDER_PREFIX + phoneRegisterDto.getPhone();
        sendVerifyCode(prefixAndPhone);
    }


    /*
    * 发送注册手机验证码
    * */
    private void sendRegisterCode(PhoneRegisterDto phoneRegisterDto) {
        //        1.参数非空校验

        String imageCodeKey = phoneRegisterDto.getImageCodeKey();
        String imageCode = phoneRegisterDto.getImageCode();
        if (StringUtils.isBlank(imageCodeKey)
                ||StringUtils.isBlank(imageCode)){
            throw new BusinessException("参数不能为空");
        }
//        2.验证图形验证码是否正确
        Object imageCodeInRedis = redisTemplate.opsForValue().get(imageCodeKey);
        if (imageCodeInRedis == null){
            throw new BusinessException("图形验证码已经过期");
        }
        if (!imageCodeInRedis.toString().equalsIgnoreCase(imageCode)){
            throw new BusinessException("图形验证码错误");
        }
//        3.查询手机号是否被注册
        User userInDb = userMapper.loadByPhone(phoneRegisterDto.getPhone());
        if (userInDb != null){
            throw new BusinessException("手机号已注册，请直接登录");
        }
        String  prefixAndPhone = BaseConstants.VerifyCodeConstants.USER_PHONE_REGISTER_PREFIX + phoneRegisterDto.getPhone();
        sendVerifyCode(prefixAndPhone);

    }

    private void sendVerifyCode(String prefixAndPhone){
        //        4.通过   业务键（register:）+手机号   获取是否存在短信验证码
        Object smsCodeAndTimeInRedis = redisTemplate.opsForValue().get(prefixAndPhone);//952768:987988946784978
        String smsCode;
//        4.1.不存在（第一次发送或者过期）
        if (smsCodeAndTimeInRedis == null){
//        4.1.1.生成手机验证码
            smsCode = StrUtils.getComplexRandomString(6);

        }else {
            //        4.2.存在
//        4.2.1.判断发送时间是否小于1分钟
            Long currentTime = System.currentTimeMillis();
            String[] smsCodeAndTimeArr = smsCodeAndTimeInRedis.toString().split(":");
            Long oldTime = Long.valueOf(smsCodeAndTimeArr[1]);//这个是发送验证码时候的时间戳
            if (currentTime- oldTime <1 * 60 * 1000){
                //        4.2.1.1.如果小于1分钟 使劲骂 滚！
                throw new BusinessException("滚！！！");
            }
//        4.2.1.2.如果大于1分钟 取出验证码，为key,以  验证码+“：”+当前时间戳 为value,把验证码存入redis
            smsCode = smsCodeAndTimeArr[0];
        }
        //        4.1.2.以   业务键（register:）+手机号  为key,以  验证码+“：”+当前时间戳 为value,把验证码存入redis
        redisTemplate.opsForValue().set(prefixAndPhone, smsCode + ":" + System.currentTimeMillis(), 5,TimeUnit.MINUTES);
//        4.1.3.发送手机验证码给用户
//        SmsUtil.sendSms(phone,"亲，您的验证码是：" + smsCode + ",请在五分钟以内使用");
        System.out.println("亲，您的验证码是：" + smsCode + ",请在五分钟以内使用");
    }
}
